module executor.rpc.RpcRequest;

import msgtrans;
import message.Constants;
import message.MsgDefine;
import google.protobuf;
import hunt.logging;
import std.array;
import std.conv : to;
import hunt.util.Serialize;
import client.GateServerClient;
import client.MsgServerClient;
import service.SearchUserService;
import service.ApplyService;
import std.json;
import core.stdc.string;
import comm.comm;
import bootstrap.DatabaseBootstrap;
import core.stdc.time;
import hunt.framework;
import service.RpcService;
import repository.RedEnvelopeRepository;
import model.RedEnvelope;
import std.uuid;
import repository.UserAssetsRepository;
import model.UserAssets;
import service.FriendService;
import comm.UploadToken;

// import app.grpc.Common:ErrorCode;

/**
红包模块
**/

@TransportServer(LogicServerName)
class RpcRequest : AbstractExecutor!(RpcRequest)
{

    @MessageId(MESSAGE.CMD_RPC_REQUEST)
    void rpcRequest(TransportContext ctx, MessageBuffer buffer)
    {
        auto req = new RPC_REQUEST();
        buffer.data.fromProtobuf!RPC_REQUEST(req);

        ServerExtend serverExtend;
        memcpy(&serverExtend, buffer.extend.ptr, ServerExtend.sizeof);

        string json;

        switch (req.route)
        {
            case "redpacket.send": //发送红包接口
            {
                SendRedEnvelopeReq jsonObj = DecodeSendRedEnvelope(req.content);

                //TODO: 给自己发送红包的这个判断不合理，暂时去掉
                // // if (FriendService.isSelf(to!string(serverExtend.userId),
                // //         to!string(jsonObj.target_id)))
                // // {
                // //     ErrorObj obj;
                // //     import message.MsgDefine;

                // //     obj.code = ErrorCode.ERR_NOT_SUPPORT_YOURSELF;
                // //     obj.message = "不支持自己发给自己红包";
                // //     json = EncodeJsonValue(obj);
                // //     break;
                // // }

                if ((jsonObj.amount / jsonObj.count) > 200000000)
                {
                    ErrorObj obj;
                    import message.MsgDefine;

                    obj.code = ErrorCode.ERR_RED_ENVELOPE_LIMITE;
                    obj.message = "超过200万上限";
                    json = EncodeJsonValue(obj);
                    break;
                }

                int id = dealRedPacketSend(jsonObj, serverExtend.userId);
                if (id >= 0)
                {
                    import message.MsgDefine;

                    json = EncodeSendRedEnvelope(ErrorCode.ERR_NONE, id);
                    Msg msg = new Msg;
                    msg.chatId = to!string(jsonObj.target_id);
                    msg.fromUserId = to!string(serverExtend.userId);
                    msg.type = MsgType.RED_ENVELOPE;
                    msg.messageId = jsonObj.message_id;//to!string(id);
                    //把生成的红包ID加入到json中
                    msg.message = EncodeRedEnvelope(req.content, id);
                    msg.msgTime = core.stdc.time.time(null);
                    auto msgClient = MsgServerClient.getInstance()
                        .getForwardClient(jsonObj.target_id);//TODO: 发送使用target_id???????????????
                    msgClient.send(new MessageBuffer(MESSAGE.CMD_MESSAGE_TRANSFER,
                            msg.toProtobuf.array));

                    logInfo("send red %s %s %s", msg.chatId, msg.fromUserId, msg.messageId);
                }
                else
                {
                    if (id == -2)
                    {
                        ErrorObj obj;
                        import message.MsgDefine;

                        obj.code = ErrorCode.ERR_BALANCE;
                        obj.message = "余额不足";
                        json = EncodeJsonValue(obj);
                    }
                    else
                    {
                        ErrorObj obj;
                        import message.MsgDefine;

                        obj.code = ErrorCode.ERR_DB;
                        obj.message = "数据库错误";
                        json = EncodeJsonValue(obj);
                    }
                }
                break;
            }
            case "redpacket.detail": //查看红包接口
            {

                import message.MsgDefine;

                GetRedEnvelopeReq jsonObj = DecodeGetRedEnvelope(req.content);
                logInfo("detail red %s", jsonObj.red_packet_id);
                json = dealLookPacketGet(jsonObj, serverExtend.userId);

                //if (get)
                //{
                //  Msg msg = new Msg;
                //  msg.chatId = to!string(chatId);
                //  msg.fromUserId = to!string(serverExtend.userId);
                //  msg.type = MsgType.NOTICE_RED_ENVELOPE;
                //  // msg.messageId = to!string(id);
                //  //msg.message = req.content;
                //  msg.localId = to!string(fromId);
                //  msg.msgTime = core.stdc.time.time(null);
                //  auto msgClient =  MsgServerClient.getInstance().getForwardClient(cast(int)fromId);
                //  msgClient.send(new MessageBuffer(MESSAGE.CMD_MESSAGE_TRANSFER, msg.toProtobuf.array));
                //}
                break;
            }
            case "redpacket.open": //打开红包接口
            {
                import message.MsgDefine;

                bool get = false;
                ulong fromId = 0;
                ulong chatId = 0;
                GetRedEnvelopeReq jsonObj = DecodeGetRedEnvelope(req.content);
                json = dealGetPacketGet(jsonObj, serverExtend.userId, get, fromId, chatId);

                if (get)
                {
                    Msg msg = new Msg;
                    msg.chatId = to!string(chatId);
                    msg.fromUserId = to!string(serverExtend.userId);
                    msg.type = MsgType.NOTICE_RED_ENVELOPE;
                    msg.messageId = randomUUID().toString();
                    msg.message = to!string(jsonObj.red_packet_id);
                    msg.localId = to!string(fromId);
                    msg.msgTime = core.stdc.time.time(null);
                    auto msgClient = MsgServerClient.getInstance()
                        .getForwardClient(cast(int) fromId);
                    msgClient.send(new MessageBuffer(MESSAGE.CMD_MESSAGE_TRANSFER,
                            msg.toProtobuf.array));

                    logInfo("get red %s %s %s", msg.chatId, msg.localId,  msg.fromUserId);
                
                }
                break;
            }
            case "file.upload_token":
            {
                string token = rndStr(32);

                auto uploadToken = new UploadToken;
                uploadToken.user_id = serverExtend.userId.to!string;
                uploadToken.token = token;
                uploadToken.time = time();

                Application.instance().redis().set("upload:token:" ~ token, toJson(uploadToken).toString());
                json = RPCResponseEncode(uploadToken.toJson());
                
                logInfo("RPC: file.upload_token is %s", uploadToken.token);

                break;
            }
            default:
            {
                break;
            }
        }

        auto res = new RPC_RESPONSE();
        res.content = json;
        res.src = req.src;

        ubyte[] extend;
        extend = buffer.extend;
        logInfo("rpcRequest ----- %s", res.content);
        ctx.session.send(new MessageBuffer(MESSAGE.CMD_RPC_RESPONST, res.toProtobuf.array, extend));
    }

    int dealRedPacketSend(SendRedEnvelopeReq req, ulong userId)
    {
        UserAssetsRepository userAssetRep = new UserAssetsRepository;
        UserAssets userAsset = userAssetRep.getStatus(to!int(userId));
        if (userAsset is null)
        {
            userAsset = new UserAssets;
            userAsset.id = to!uint(userId);
            userAsset.assets = 1000000000;
            userAssetRep.putUserAssets(userAsset);
        }
        if (req.amount > userAsset.assets)
        {
            return -2;
        }
        long[] split;
        if (req.type == 1)
        {
            split = SplitRedPacket(req.amount, req.count);
        }
        else
        {
            split = averageSplitRedPacket(req.amount, req.count);
        }

        return RpcService.sendRedEnvelope(req, split, userId, userAsset.assets);
    }

    void checkGetRedPacket(RedEnvelope obj, ulong userId,
            out message.MsgDefine.ErrorCode errCode, out string errMsg)
    {
        if (obj is null)
        {
            errCode = message.MsgDefine.ErrorCode.ERR_DB;
            errMsg = "红包不存在";
            return;
        }
        if (obj.status != 0)
        {
            errCode = message.MsgDefine.ErrorCode.ERR_DB;
            errMsg = "红包状态不对";
            return;
        }

        errCode = message.MsgDefine.ErrorCode.ERR_NONE;
        errMsg = "";
        return;
    }

    string dealGetPacketGet(GetRedEnvelopeReq req, ulong userId, out bool get,
            out ulong fromId, out ulong chatId)
    {
        //TODO: 红包的发送，获取信息，打开都应该加合法性验证，比如能否发送，能否获取信息，能否抢，是否重复抢，红包是否过期，红包是否抢完
        RedEnvelopeRepository redRepo = new RedEnvelopeRepository;
        RedEnvelope RedEnvobj = redRepo.getStatus(req.red_packet_id);

        UserAssetsRepository userAssetRep = new UserAssetsRepository;
        UserAssets userAsset = userAssetRep.getStatus(to!int(userId));
        if (userAsset is null)
        {
            userAsset = new UserAssets;
            userAsset.id = to!uint(userId);
            userAsset.assets = 1000000000;
            userAssetRep.putUserAssets(userAsset);
        }

        if (RedEnvobj !is null)
        {
            logInfo("get red 263 %s %s %s %s", userId, RedEnvobj.id, RedEnvobj.fromId, RedEnvobj.chatId );

            fromId = cast(ulong) RedEnvobj.fromId;
            chatId = cast(ulong) RedEnvobj.chatId;

            ErrorObj obj;
            import message.MsgDefine;

            checkGetRedPacket(RedEnvobj, userId, obj.code, obj.message);

            if (obj.code == ErrorCode.ERR_NONE)
            {
                logInfo("get red 275");

                return RpcService.getRedEnvelope(RedEnvobj.id, userId, RedEnvobj, userAsset, get);
            }
            else
            {
                return EncodeJsonValue(obj);
            }
             // if (RedEnvobj.status == 0)
                // {
                //     return RpcService.getRedEnvelope(RedEnvobj.id,userId,RedEnvobj,userAsset ,get );
                // }else {

                //     obj.code = ErrorCode.ERR_EXPIRE;
                //     obj.message = "红包过期了";
                //     return EncodeJsonValue(obj);s
                // }
        }
        else
        {
            ErrorObj obj;
            import message.MsgDefine;

            obj.code = message.MsgDefine.ErrorCode.ERR_DB;
            obj.message = "红包不存在";
            return EncodeJsonValue(obj);
        }
    }

    string dealLookPacketGet(GetRedEnvelopeReq req, ulong userId)
    {
        //TODO: 不应该使用自增ID作为红包ID
        RedEnvelopeRepository redRepo = new RedEnvelopeRepository;
        RedEnvelope RedEnvobj = redRepo.getStatus(req.red_packet_id);
        return RpcService.lookRedEnvelope(req.red_packet_id, userId, RedEnvobj);
    }
}
